# -*- mode: makefile;-*-
#
# Copyright (C) 1999-2016 Apple Inc. All rights reserved.
#
# MakeInc.rule defines the targets and rules for
# leaf directories once MakeInc.dir has recursed
# into them. "do_XXX" may be double-colon rules
# to allow the Makefile in the source directory
# to augment the actions that will be performed.
#

#
# Generic Install rules
#

ifndef INSTALL_KF_MI_LCL_LIST
    INSTALL_KF_MI_LCL_LIST = $(EXPORT_MI_LIST)
endif

ifndef INSTALL_KF_MI_LCL_GEN_LIST
    INSTALL_KF_MI_LCL_GEN_LIST = $(EXPORT_MI_GEN_LIST)
endif

ifndef INSTALL_KF_MD_LCL_LIST
    INSTALL_KF_MD_LCL_LIST = $(EXPORT_MD_LIST)
endif

ifndef INSTALL_KF_MD_LCL_GEN_LIST
    INSTALL_KF_MD_LCL_GEN_LIST = $(EXPORT_MD_GEN_LIST)
endif

ifndef INSTALL_KF_MI_LIST
    INSTALL_KF_MI_LIST = $(EXPORT_MI_LIST)
endif

ifndef INSTALL_KF_MI_GEN_LIST
    INSTALL_KF_MI_GEN_LIST = $(EXPORT_MI_GEN_LIST)
endif

ifndef INSTALL_KF_MD_LIST
    INSTALL_KF_MD_LIST = $(EXPORT_MD_LIST)
endif

ifndef INSTALL_KF_MD_GEN_LIST
    INSTALL_KF_MD_GEN_LIST = $(EXPORT_MD_GEN_LIST)
endif

ifeq (${XNU_LOGCOLORS},y)
    LOGCOLORS ?= y
endif

ifeq ($(LOGCOLORS),y)
    # Get a nice list of device code names associated with the build platform
    ifndef CDevs
        #ifdef EMBEDDED_DEVICE_MAP
        #    export CDevs := $(shell $(EMBEDDED_DEVICE_MAP) -db $(EDM_DBPATH) -query "SELECT DISTINCT TargetType FROM Targets WHERE KernelPlatform = '$(CURRENT_MACHINE_CONFIG_LC)'" | tr '[\r\n]' ':' | sed 's,:$$,,')
        #endif
    endif
    ifndef CMD_MC
        export _MACHINE := $(CURRENT_MACHINE_CONFIG_LC)
        ifeq ($(CURRENT_MACHINE_CONFIG),NONE)
            export _MACHINE := $(subst Mac,,$(PLATFORM))
        endif
        export CMD_MC := \\033[1m$(shell __A="$(CURRENT_ARCH_CONFIG_LC)"; \
                                         __As=$$((6-$${\#__A})); \
                                         printf "%-.6s%*.*s %9.9s" \
                                                "$${__A}" \
                                                $${__As} $${__As} " " \
                                                "$(_MACHINE)")\\033[m
    endif
    # Turn off colored output
    Color0=\\033[m
    # Start a host command: bold, underlined pink text
    ColorH=\\033[1;4;35m
    # Start a compilation-related command: bold, underlined blue text
    ColorC=[$(CMD_MC)] \\033[1;4;34m
    # Start a MIG command: bold, green text on light grey background
    ColorM=[$(CMD_MC)] \\033[1;32;40m
    # Start a linking command: bold, white text on blue background
    ColorL=[$(CMD_MC)] \\033[1;37;44m
    # Start a filename: bold, white text
    ColorF=\\033[1;37m
    # Start a linked file name: yellow text on light grey background
    ColorLF=\\033[1;33;40m
    # Error strings: underlined bold white text on red background
    ColorErr=\033[1;4;37;41m
endif

.PHONY: ALWAYS

ALWAYS:

# $(1) is the list of install paths
# $(2) is "1" if it's a "GEN"-style rule that looks locally, or else $(SOURCE)
# $(3) is the local temp directory for processing
# $(4) is the unifdef flags
#
# $$$$$$$$ is a double-escaped "$$" to represent the current pid
# of the shell process for creating uniquely named temporary files

define INSTALLHDRS_RULE_template

.PHONY: $(3)_MKDIR

$(3)_MKDIR:
	$$(_v)$$(MKDIR) ./$(3)
	$$(_v)$$(MKDIR) $(dir $(firstword $(1)))

# Rebuild if unifdef flags change
$(1): $(3)/.UNIFDEF_FLAGS
$(3)/.UNIFDEF_FLAGS: ALWAYS | $(3)_MKDIR
	$$(_v)$$(REPLACECONTENTS) $$@ $$(UNIFDEF) $(4)

$(1): $(dir $(firstword $(1)))% : $(if $(2),%,$$(SOURCE)/%) | $(3)_MKDIR
	@echo "$$(ColorH)INSTALLHDR$(Color0)    $$(ColorF)$$*$$(Color0)"
	$$(_v)$$(UNIFDEF) $(4) $$< > ./$(3)/$$*.unifdef.$$$$$$$$;	\
	if [ $$$$? -eq 2 ]; then						\
		echo Parse failure for $$<;				\
		exit 1;							\
	fi;								\
	$$(DECOMMENT) ./$(3)/$$*.unifdef.$$$$$$$$ r >			\
		./$(3)/$$*.strip.$$$$$$$$ || exit 1;			\
	if [ -s ./$(3)/$$*.strip.$$$$$$$$ ]; then			\
		$$(INSTALL) $$(INSTALL_FLAGS) ./$(3)/$$*.unifdef.$$$$$$$$ $$@ || exit 1;	\
	fi;								\
	$$(RM) ./$(3)/$$*.unifdef.$$$$$$$$ ./$(3)/$$*.strip.$$$$$$$$
endef

#
# Machine-independent (public) files
#

INSTALL_MI_INC_FILES = $(addprefix $(DSTROOT)/$(INCDIR)/$(INSTALL_MI_DIR)/, $(INSTALL_MI_LIST))
INSTALL_MI_INC_GEN_FILES = $(addprefix $(DSTROOT)/$(INCDIR)/$(INSTALL_MI_DIR)/, $(INSTALL_MI_GEN_LIST))

$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_MI_INC_FILES),,incmidir,$(SINCFRAME_UNIFDEF)))
$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_MI_INC_GEN_FILES),1,incmigendir,$(SINCFRAME_UNIFDEF)))

INSTALL_KF_MI_FILES = $(addprefix $(DSTROOT)/$(KINCDIR)/$(EXPORT_MI_DIR)/, $(INSTALL_KF_MI_LIST))
INSTALL_KF_MI_GEN_FILES = $(addprefix $(DSTROOT)/$(KINCDIR)/$(EXPORT_MI_DIR)/, $(INSTALL_KF_MI_GEN_LIST))

$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_KF_MI_FILES),,kincmidir,$(KINCFRAME_UNIFDEF)))
$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_KF_MI_GEN_FILES),1,kincmigendir,$(KINCFRAME_UNIFDEF)))

#
# Machine-independent local (private) files
#

INSTALL_MI_LCL_FILES = $(addprefix $(DSTROOT)/$(LCLDIR)/$(INSTALL_MI_DIR)/, $(sort $(INSTALL_MI_LCL_LIST) $(INSTALL_MI_LIST)))
INSTALL_MI_LCL_GEN_FILES = $(addprefix $(DSTROOT)/$(LCLDIR)/$(INSTALL_MI_DIR)/, $(sort $(INSTALL_MI_LCL_GEN_LIST) $(INSTALL_MI_GEN_LIST)))

$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_MI_LCL_FILES),,pincmidir,$(SPINCFRAME_UNIFDEF)))
$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_MI_LCL_GEN_FILES),1,pincmigendir,$(SPINCFRAME_UNIFDEF)))

INSTALL_KF_MI_LCL_FILES = $(addprefix $(DSTROOT)/$(KPINCDIR)/$(EXPORT_MI_DIR)/, $(INSTALL_KF_MI_LCL_LIST))
INSTALL_KF_MI_LCL_GEN_FILES = $(addprefix $(DSTROOT)/$(KPINCDIR)/$(EXPORT_MI_DIR)/, $(INSTALL_KF_MI_LCL_GEN_LIST))

$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_KF_MI_LCL_FILES),,kpincmidir,$(KPINCFRAME_UNIFDEF)))
$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_KF_MI_LCL_GEN_FILES),1,kpincmigendir,$(KPINCFRAME_UNIFDEF)))

#
# Machine-dependent (public) files
#

INSTALL_MD_INC_FILES = $(addprefix $(DSTROOT)/$(INCDIR)/$(INSTALL_MD_DIR)/, $(INSTALL_MD_LIST))
INSTALL_MD_INC_GEN_FILES = $(addprefix $(DSTROOT)/$(INCDIR)/$(INSTALL_MD_DIR)/, $(INSTALL_MD_GEN_LIST))

$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_MD_INC_FILES),,incdir,$(SINCFRAME_UNIFDEF)))
$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_MD_INC_GEN_FILES),1,incgendir,$(SINCFRAME_UNIFDEF)))

INSTALL_KF_MD_FILES = $(addprefix $(DSTROOT)/$(KINCDIR)/$(EXPORT_MD_DIR)/, $(INSTALL_KF_MD_LIST))
INSTALL_KF_MD_GEN_FILES = $(addprefix $(DSTROOT)/$(KINCDIR)/$(EXPORT_MD_DIR)/, $(INSTALL_KF_MD_GEN_LIST))

$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_KF_MD_FILES),,kincdir,$(KINCFRAME_UNIFDEF)))
$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_KF_MD_GEN_FILES),1,kincgendir,$(KINCFRAME_UNIFDEF)))

#
# Machine-dependent local (private) files
#

INSTALL_MD_LCL_FILES = $(addprefix $(DSTROOT)/$(LCLDIR)/$(INSTALL_MD_DIR)/, $(sort $(INSTALL_MD_LCL_LIST) $(INSTALL_MD_LIST)))
INSTALL_MD_LCL_GEN_FILES = $(addprefix $(DSTROOT)/$(LCLDIR)/$(INSTALL_MD_DIR)/, $(sort $(INSTALL_MD_LCL_GEN_LIST) $(INSTALL_MD_GEN_LIST)))

$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_MD_LCL_FILES),,pincdir,$(SPINCFRAME_UNIFDEF)))
$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_MD_LCL_GEN_FILES),1,pincgendir,$(SPINCFRAME_UNIFDEF)))

INSTALL_KF_MD_LCL_FILES = $(addprefix $(DSTROOT)/$(KPINCDIR)/$(EXPORT_MD_DIR)/, $(INSTALL_KF_MD_LCL_LIST))
INSTALL_KF_MD_LCL_GEN_FILES = $(addprefix $(DSTROOT)/$(KPINCDIR)/$(EXPORT_MD_DIR)/, $(INSTALL_KF_MD_LCL_GEN_LIST))

$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_KF_MD_LCL_FILES),,kpincdir,$(KPINCFRAME_UNIFDEF)))
$(eval $(call INSTALLHDRS_RULE_template,$(INSTALL_KF_MD_LCL_GEN_FILES),1,kpincgendir,$(KPINCFRAME_UNIFDEF)))

.PHONY: do_installhdrs_mi

# Double-colon rule so that MakeInc.kernel can add custom behaviors
do_installhdrs_mi:: $(INSTALL_MI_INC_FILES) $(INSTALL_MI_INC_GEN_FILES) $(INSTALL_KF_MI_FILES) $(INSTALL_KF_MI_GEN_FILES) \
		    $(INSTALL_MI_LCL_FILES) $(INSTALL_MI_LCL_GEN_FILES) $(INSTALL_KF_MI_LCL_FILES) $(INSTALL_KF_MI_LCL_GEN_FILES)
	@:

.PHONY: do_installhdrs_md

do_installhdrs_md: $(INSTALL_MD_INC_FILES) $(INSTALL_MD_INC_GEN_FILES) $(INSTALL_KF_MD_FILES) $(INSTALL_KF_MD_GEN_FILES) \
		   $(INSTALL_MD_LCL_FILES) $(INSTALL_MD_LCL_GEN_FILES) $(INSTALL_KF_MD_LCL_FILES) $(INSTALL_KF_MD_LCL_GEN_FILES)
	@:

#
# Generic Export rules
#
EXPORT_MI_INC_FILES = $(addprefix $(OBJROOT)/$(EXPDIR)/$(EXPORT_MI_DIR)/, $(EXPORT_MI_LIST))
EXPORT_MI_GEN_INC_FILES = $(addprefix $(OBJROOT)/$(EXPDIR)/$(EXPORT_MI_DIR)/, $(EXPORT_MI_GEN_LIST))

.PHONY: EXP_MI_INC_DIR

EXP_MI_INC_DIR:
	$(_v)$(MKDIR) $(OBJROOT)/$(EXPDIR)/$(EXPORT_MI_DIR)

$(EXPORT_MI_GEN_INC_FILES): $(OBJROOT)/$(EXPDIR)/$(EXPORT_MI_DIR)/% : % | EXP_MI_INC_DIR
	$(_v)$(INSTALL) $(DATA_INSTALL_FLAGS) $< $@

$(EXPORT_MI_INC_FILES): $(OBJROOT)/$(EXPDIR)/$(EXPORT_MI_DIR)/% : $(SOURCE)/% | EXP_MI_INC_DIR
	$(_v)$(INSTALL) $(DATA_INSTALL_FLAGS) $< $@

EXPORT_MD_INC_FILES = $(addprefix $(OBJROOT)/$(EXPDIR)/$(EXPORT_MD_DIR)/, $(EXPORT_MD_LIST))
EXPORT_MD_GEN_INC_FILES = $(addprefix $(OBJROOT)/$(EXPDIR)/$(EXPORT_MD_DIR)/, $(EXPORT_MD_GEN_LIST))

.PHONY: EXP_MD_INC_DIR

EXP_MD_INC_DIR:
	$(_v)$(MKDIR) $(OBJROOT)/$(EXPDIR)/$(EXPORT_MD_DIR)

$(EXPORT_MD_GEN_INC_FILES): $(OBJROOT)/$(EXPDIR)/$(EXPORT_MD_DIR)/% : % | EXP_MD_INC_DIR
	$(_v)$(INSTALL) $(DATA_INSTALL_FLAGS) $< $@

$(EXPORT_MD_INC_FILES): $(OBJROOT)/$(EXPDIR)/$(EXPORT_MD_DIR)/% : $(SOURCE)/% | EXP_MD_INC_DIR
	$(_v)$(INSTALL) $(DATA_INSTALL_FLAGS) $< $@

.PHONY: do_exporthdrs_mi

do_exporthdrs_mi: $(EXPORT_MI_GEN_INC_FILES) $(EXPORT_MI_INC_FILES)
	@:

.PHONY: do_exporthdrs_md

do_exporthdrs_md: $(EXPORT_MD_GEN_INC_FILES)  $(EXPORT_MD_INC_FILES)
	@:

#
# Generic Compilation rules
#

#
# Compilation rules to generate .o from .s
#

S_RULE_0=@echo "$(ColorC)AS$(Color0)  $(ColorF)$@$(Color0)"
S_RULE_1A=$(_v)${S_KCC} -c ${SFLAGS} -MD -MF $(@:o=d) -MP ${$@_SFLAGS_ADD} ${INCFLAGS} ${$@_INCFLAGS}
S_RULE_1B=$(<F)
S_RULE_2=

#
# Compilation rules to generate .o from .c for normal files
#
C_RULE_0=@echo "$(ColorC)CC$(Color0)  $(ColorF)$@$(Color0)"
C_RULE_1A=$(_v)${KCC} -c ${filter-out ${$@_CFLAGS_RM}, ${CFLAGS} ${CWARNFLAGS}} -MD -MF $(@:o=d) -MP ${$@_CFLAGS_ADD} ${$@_CWARNFLAGS_ADD} ${INCFLAGS} ${$@_INCFLAGS}
C_RULE_1B=$(<F)
ifeq ($(BUILD_MACHO_OBJ),0)
C_RULE_2=
else ifeq ($(DO_CTFCONVERT),1)
C_RULE_2=$(_v)if [ -z "${$@_SKIP_CTFCONVERT}" ]; then \
                  ctferr=`${CTFCONVERT} -l xnu -v -o $@.ctf $@ 2>&1 > /dev/null || true`; \
                  if [ ! -z "$${ctferr}" ]; then \
                      echo "[$(CMD_MC)] $(ColorErr)$@$(Color0)  $(ColorErr)$${ctferr}$(Color0)"; \
                  fi; \
              fi
else
C_RULE_2=
endif
ifeq ($(DO_CTFMACHO), 1)
C_CTFRULE_1A=$(_v)${KCC} -o $@.non_lto -c ${filter-out ${$@_CFLAGS_RM}, ${CFLAGS} ${CWARNFLAGS}} ${$@_CFLAGS_ADD} ${$@_CWARNFLAGS_ADD} ${INCFLAGS} $(CFLAGS_NOLTO_FLAG) ${$@_INCFLAGS}
C_CTFRULE_1B=$(<F)
C_CTFRULE_2=$(_v)if [ -z "${$@_SKIP_CTFCONVERT}" ]; then \
                     ctferr=`${CTFCONVERT} -l xnu -v -o $@.non_lto.ctf $@.non_lto 2>&1 > /dev/null || true`; \
                     if [ ! -z "$${ctferr}" ]; then \
                         echo "[$(CMD_MC)] $(ColorErr)$@$(Color0)  $(ColorErr)$${ctferr}$(Color0)"; \
                     fi; \
                 fi
else
C_CTFRULE_1A=@true 
C_CTFRULE_1B=
C_CTFRULE_2=@true 
endif

C_RULE_3=@true 
C_RULE_4A=@true 
C_RULE_4B=

#
# Compilation rules to generate .o from .c for driver files
#
C_RULE_0_D=${C_RULE_0}
C_RULE_1A_D=${C_RULE_1A}
C_RULE_1B_D=${C_RULE_1B}
C_RULE_2_D=${C_RULE_2}
C_RULE_3_D=${C_RULE_3}
C_RULE_4A_D=${C_RULE_4A}
C_RULE_4B_D=${C_RULE_4B}
C_CTFRULE_1A_D=${C_CTFRULE_1A}
C_CTFRULE_1B_D=${C_CTFRULE_1B}
C_CTFRULE_2_D=${C_CTFRULE_2}
C_CTFRULE_3_D=${C_CTFRULE_3}

#
# Compilation rules to generate .co from .cp or .cpo from .cpp
#   The config tool slickly changes the last source filename char to 'o'
#   for the object filename.
P_RULE_0=@echo "$(ColorC)C++$(Color0) $(ColorF)$@$(Color0)"
P_RULE_1A=$(_v)${KC++} -o $@ -c ${CXXFLAGS} ${filter-out ${$@_CFLAGS_RM}, ${CFLAGS} ${CXXWARNFLAGS}} -MD -MF $(@:o=d) -MP ${$@_CFLAGS_ADD} ${$@_CXXWARNFLAGS_ADD} ${INCFLAGS} ${$@_INCFLAGS}
P_RULE_1B=$(<F)
P_RULE_2=
P_CTFRULE_1A=@true 
P_CTFRULE_1B=
P_CTFRULE_2=@true 

P_RULE_3=@true 
P_RULE_4A=@true 
P_RULE_4B=

#
# This isn't the right place to put this, but we need to := override some settings
# in Makefiles that include the generic helper fragments (like this file)
#
ifeq ($(BUILD_JSON_COMPILATION_DATABASE),1)
HIB_FILES :=
LAST_FILES :=
KLD_FILES :=
endif

.PHONY: do_build_all

# Do-nothing rule, since not all levels of the recursive hierarchy might implement this
# in their local Makefiles. Those that do will use a "::" rule to augment this.
do_build_all::
	@:

.PHONY: do_build_install_primary

# Do-nothing rule, since not all levels of the recursive hierarchy might implement this
# in their local Makefiles. Those that do will use a "::" rule to augment this.
do_build_install_primary::
	@:

.PHONY: do_build_install_non_primary

# Do-nothing rule, since not all levels of the recursive hierarchy might implement this
# in their local Makefiles. Those that do will use a "::" rule to augment this.
do_build_install_non_primary::
	@:

INSTALL_MAN_FILES = $(addprefix $(DSTROOT)/$(MANDIR)/$(INSTALL_MAN_DIR)/, $(INSTALL_MAN_LIST))

.PHONY: INSTALL_MAN_DIR

INSTALL_MAN_DIR:
	$(_v)$(MKDIR) $(DSTROOT)/$(MANDIR)/$(INSTALL_MAN_DIR)

$(INSTALL_MAN_FILES): $(DSTROOT)/$(MANDIR)/$(INSTALL_MAN_DIR)/% : % | INSTALL_MAN_DIR
	@echo "$(ColorH)MAN$(Color0)        $(ColorF)$*$(Color0)"
	$(_v)$(INSTALL) $(INSTALL_FLAGS) $< $@

define MAN_LINKS_RULE_template
$$(DSTROOT)/$$(MANDIR)/$$(INSTALL_MAN_DIR)/$(2): $$(DSTROOT)/$$(MANDIR)/$$(INSTALL_MAN_DIR)/$(1)
	@echo "$$(ColorH)MANLINK$$(Color0)    $$(ColorF)$(2)$$(Color0)"
	$(_v)ln -f $$< $$@
endef

function_generate_man_links_rules = $(if $(word 1,$(1)),$(eval $(call MAN_LINKS_RULE_template,$(word 1,$(1)),$(word 2,$(1)))) $(DSTROOT)/$(MANDIR)/$(INSTALL_MAN_DIR)/$(word 2,$(1)) $(call function_generate_man_links_rules,$(wordlist 3,$(words $(1)),$(1))))

INSTALL_MAN_FILES_LINKS = $(call function_generate_man_links_rules,$(INSTALL_MAN_LINKS))

.PHONY: do_installman

do_installman: $(INSTALL_MAN_FILES) $(INSTALL_MAN_FILES_LINKS)
	@:

.PHONY: do_textfiles_install

# Do-nothing rule, since not all levels of the recursive hierarchy might implement this
# in their local Makefiles. Those that do will use a "::" rule to augment this.
do_textfiles_install:: do_installman
	@:

.PHONY: do_build_setup

# Do-nothing rule, since not all levels of the recursive hierarchy might implement this
# in their local Makefiles. Those that do will use a "::" rule to augment this.
do_build_setup::
	@:

.PHONY: do_config_all

# Do-nothing rule, since not all levels of the recursive hierarchy might implement this
# in their local Makefiles. Those that do will use a "::" rule to augment this.
do_config_all::
	@:

.PHONY: do_config_install

# Do-nothing rule, since not all levels of the recursive hierarchy might implement this
# in their local Makefiles. Those that do will use a "::" rule to augment this.
do_config_install::
	@:

# vim: set ft=make:
